<template>
  <div>
    <PageTitleSearch
      :title="'整体经营情况'"
      :hotelList="hotelList"
      :currentHotel="currentHotel"
      v-model:lastMonth="lastMonth"
      :currentAcc="currentAcc"
      @hotel-change="handleSelectChange"
      @date-change="handleDateSelect"
      @acc-change="handleAccSelect"
    />
    <div class="main-content">
      <div class="content-wrapper">
        <div class="left-section">
          <div class="total-income">
            <div class="total-left">
              <span class="label">总收入</span>
              <span class="amount unline">{{ totalIncome.actual ? formatAmount(totalIncome.actual) : totalIncome.actual }}万元</span>
            </div>
            <div class="total-right">
              <div class="budget-line">
                <span class="label">预算：{{ formatAmount(totalIncome.budget) }}</span>
                <span class="diff" :class="{ up: totalIncome.actual >= totalIncome.budget, down: totalIncome.actual < totalIncome.budget }">
                  {{ totalIncome.actual >= totalIncome.budget ? '+' : '' }}{{ formatAmount(totalIncome.actual - totalIncome.budget) }}
                </span>
                <div class="rate">
                  <i class="triangle" :class="{ up: totalIncome.actual >= totalIncome.budget, down: totalIncome.actual < totalIncome.budget }"></i>
                  <span :class="{ up: totalIncome.actual >= totalIncome.budget, down: totalIncome.actual < totalIncome.budget }">
                    {{ formatPercent(totalIncome.actual / totalIncome.budget) }}
                  </span>
                </div>
              </div>
              <div class="border-dashed"></div>
              <div class="last-year-line">
                <span class="label">去年：{{ formatAmount(totalIncome.lActual) }}</span>
                <span class="diff" :class="{ up: totalIncome.actual >= totalIncome.lActual, down: totalIncome.actual < totalIncome.lActual }">
                  {{ totalIncome.actual >= totalIncome.lActual ? '+' : '' }}{{ formatAmount(totalIncome.actual - totalIncome.lActual) }}
                </span>
                <div class="rate">
                  <i class="triangle" :class="{ up: totalIncome.actual >= totalIncome.lActual, down: totalIncome.actual < totalIncome.lActual }"></i>
                  <span :class="{ up: totalIncome.actual >= totalIncome.lActual, down: totalIncome.actual < totalIncome.lActual }">
                    {{ formatPercent((totalIncome.actual - totalIncome.lActual) / totalIncome.lActual, true) }}
                  </span>
                </div>
              </div>
            </div>
          </div>
          <div class="income-detail">
            <div v-for="item in detailItems" :key="item.code" class="detail-item">
              <div class="item-header">{{ item.name }}</div>
              <div class="item-content">
                <div class="actual">{{ formatAmount(item.actual) }}</div>
                <div class="budget">
                  <div class="budget-label">预算</div>
                  <div class="budget-value">{{ formatAmount(item.budget) }}</div>
                  <div class="budget-rate" :class="{ up: item.actual > item.budget, down: item.actual <= item.budget }">
                    <i class="triangle" :class="{ up: item.actual > item.budget, down: item.actual <= item.budget }"></i>
                    <span :class="{ up: item.actual > item.budget, down: item.actual <= item.budget }">
                      {{ formatPercent(item.actual / item.budget) }}
                    </span>
                  </div>
                </div>
                <div class="last-year">
                  <div class="last-year-label">去年</div>
                  <div class="last-year-value">{{ formatAmount(item.lActual) }}</div>
                  <div class="last-year-rate" :class="{ up: item.actual > item.lActual, down: item.actual <= item.lActual }">
                    <i class="triangle" :class="{ up: item.actual > item.lActual, down: item.actual <= item.lActual }"></i>
                    <span :class="{ up: item.actual > item.lActual, down: item.actual <= item.lActual }">
                      {{ formatPercent((item.actual - item.lActual) / item.lActual, true) }}
                    </span>
                  </div>
                </div>
              </div>
            </div>
            <div class="legend-wrap">
              <div class="detail-item legend-item">
                <div class="legend-title">单位：万元</div>
                <div class="legend-content">
                  <div class="legend-row">
                    <div class="legend-box" style="background-color: #212a7c"></div>
                    <span>实际</span>
                  </div>
                  <div class="legend-row">
                    <div class="legend-box" style="background-color: #665c99"></div>
                    <span>预算</span>
                  </div>
                  <div class="legend-row">
                    <div class="legend-triangle" style="border-bottom-color: #fda757"></div>
                    <span>去年</span>
                  </div>
                  <div class="legend-row">
                    <div class="legend-triangle" style="border-bottom-color: #000; transform: rotate(180deg)"></div>
                    <span>平均</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="income-chart" v-if="incomeList.length > 0">
            <IncomeLine :chartData="incomeList" :width="'100%'" :height="'400px'" />
          </div>
        </div>
        <div class="split-line"></div>
        <div class="right-section">
          <FlexCard title="GOP率" :loading="loading" class="gop-card">
            <RingImg v-if="gopList.length > 0" :dataList="gopList" />
          </FlexCard>
          <FlexCard title="年累计进度" :loading="loading" class="progress-card">
            <div v-if="incomeList.length > 0" class="progress-content">
              <div class="progress-time">
                <TimeProgress
                  :dataList="processIncomeList"
                  :currentMonth="parseInt(lastMonth.slice(4))"
                  v-model:lastMonth="lastMonth"
                  height="150px"
                />
              </div>
              <div v-if="incomeList.length > 0" class="progress-income">
                <IncomeProgress :dataList="processIncomeList" height="350px" />
              </div>
            </div>
          </FlexCard>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import dayjs from 'dayjs';
  import { defHttp } from '/@/utils/http/axios';
  import * as MathUtil from '/@/utils/MathUtil';
  import * as DateUtil from '/@/utils/dateUtil';
  import * as Constant from '@/utils/Constant';
  import FlexCard from '@/views/applications/ui/FlexCard.vue';
  import RingImg from '@/views/applications/ui/RingImg.vue';
  import PageTitleSearch from '@/views/applications/ui/PageTitleSearch.vue';
  import IncomeLine from '/@/views/applications/ui/IncomeLine.vue';
  import TimeProgress from '@/views/applications/ui/TimeProgress.vue';
  import IncomeProgress from '@/views/applications/ui/IncomeProgress.vue';

  const COLOR_RED = '#F53F3F';
  const COLOR_GREEN = '#00B42A';
  const COLOR_WARN = '#FDA757';
  const COLOR_GROUND = '#F7F5F4';
  const COLOR_GROUND_DEEP = '#E9E7F2';
  const COLOR_BLUE = '#212A7C';
  const COLOR_PURPLE = '#665C99';
  const REPORT_NAME = '酒店整体经营情况（项目）';
  const REPORT_CODE = 'hotel-month-single-summary';
  const INCOME_APIS = {
    month: 'getHotelMonthIncome',
    year: 'getHotelMonthAccIncome',
  };

  export default {
    name: REPORT_NAME,

    components: {
      FlexCard,
      RingImg,
      PageTitleSearch,
      IncomeLine,
      TimeProgress,
      IncomeProgress,
    },

    data() {
      return {
        reportCode: '',
        reportName: '',
        loading: false,
        tableHigh: { x: '100%', y: 308 },
        lastMonth: dayjs().subtract(1, 'month').format('YYYYMM'),
        hotelList: [],
        accList: [
          { label: '当月', value: 'month' },
          { label: '当年', value: 'year' },
        ],
        currentHotel: {},
        currentAcc: 'month',
        incomeList: [],
        yearIncomeList: [],
        processIncomeList: [],
        gopList: [
          { name: '去年', value: 0.5, color: COLOR_WARN },
          { name: '预算', value: 0.98, color: COLOR_PURPLE },
          { name: '实际', value: 0.8, color: COLOR_BLUE },
        ],
        process: 0.8,
      };
    },

    computed: {
      totalIncome() {
        let totalSum = this.incomeList
          .filter((i) => ['0101', '0102', '0105'].includes(i.subjectCode))
          .reduce(
            (acc, item) => {
              if (!acc) {
                acc = {
                  actual: 0,
                  budget: 0,
                  lActual: 0,
                };
              }
              acc.actual += item.actual || 0;
              acc.budget += item.budget || 0;
              acc.lActual += item.lActual || 0;
              return acc;
            },
            {
              actual: 0,
              budget: 0,
              lActual: 0,
            }
          );
        return (
          totalSum || {
            actual: 0,
            budget: 0,
            lActual: 0,
          }
        );
      },
      detailItems() {
        const items = [
          { code: '0101', name: '客房收入' },
          { code: '0102', name: '餐饮收入' },
          { code: '0105', name: '其他收入' },
          { code: '05', name: 'GOP' },
          { code: '06', name: 'NPI' },
        ];

        return items.map((item) => {
          const data = this.incomeList.find((i) => i.subjectCode === item.code) || {
            actual: 0,
            budget: 0,
            lActual: 0,
          };
          return {
            ...item,
            actual: data.actual || 0,
            budget: data.budget || 0,
            lActual: data.lActual || 0,
          };
        });
      },
    },

    created() {
      defHttp.get({ url: '/data/hotel/list' }, { isTransformResponse: false }).then((res) => {
        if (res.code === 200 && res.result.length > 0) {
          this.hotelList = res.result.map((s) => {
            return { label: s.name, value: s.code };
          });
          const currentHotelCode = this.$route.query.hotelCode || localStorage.getItem(Constant.STORAGE_HOTEL_NAME);
          if (currentHotelCode && res.result.filter((d) => d.code === currentHotelCode).length > 0) {
            this.currentHotel = res.result.filter((d) => d.code === currentHotelCode)[0];
          } else {
            this.currentHotel = {
              code: res.result[0].code,
              name: res.result[0].name,
            };
          }
          this.hotelSel = this.currentHotel;
          const accName = this.accList.filter((a) => a.value === this.currentAcc)[0].label;
          this.reportCode = `${REPORT_CODE}-${this.currentAcc}-${this.currentHotel.code}-${this.lastMonth}`;
          this.reportName = `${REPORT_NAME}-${accName}-${this.currentHotel.name}-${this.lastMonth}`;
          this.fetchData();
        }
      });
    },

    methods: {
      fetchData() {
        this.loading = true;
        Promise.all([
          defHttp.post({
            url: '/data/query',
            data: {
              labelCode: INCOME_APIS[this.currentAcc],
              sqlParams: [
                {
                  key: 'code',
                  value: this.currentHotel.code,
                },
                {
                  key: 'month',
                  value: this.lastMonth,
                },
              ],
              pageIndex: 1,
              pageSize: 100,
            },
          }),
          defHttp.post({
            url: '/data/query',
            data: {
              labelCode: 'getHotelMonthYearIncome',
              sqlParams: [
                {
                  key: 'code',
                  value: this.currentHotel.code,
                },
                {
                  key: 'month',
                  value: this.lastMonth,
                },
              ],
              pageIndex: 1,
              pageSize: 100,
            },
          }),
        ])
          .then(([incomeRes, yearIncomeRes]) => {
            const [incomeData, yearIncomeData] = [incomeRes.datas, yearIncomeRes.datas];

            this.incomeList = incomeData?.success && incomeData?.data ? incomeData.data : [];
            if (this.incomeList.length > 0) {
              const gop = this.incomeList.find((i) => i.subjectCode === '05') || {
                actual: 0,
                budget: 0,
                lActual: 0,
              };
              const income = this.incomeList
                .filter((i) => ['0101', '0102', '0105'].includes(i.subjectCode))
                .reduce(
                  (acc, item) => {
                    acc.actual += item.actual || 0;
                    acc.budget += item.budget || 0;
                    acc.lActual += item.lActual || 0;
                    return acc;
                  },
                  { actual: 0, budget: 0, lActual: 0 }
                );
              this.processIncomeList = [...this.incomeList];
              this.processIncomeList.push({
                ...income,
                subjectName: '总收入',
                subjectCode: '01',
              });
              this.gopList = [
                {
                  name: '去年',
                  value: this.safeDivide(gop.lActual || 0, income.lActual || 0),
                  color: COLOR_WARN,
                },
                {
                  name: '预算',
                  value: this.safeDivide(gop.budget || 0, income.budget || 0),
                  color: COLOR_PURPLE,
                },
                {
                  name: '实际',
                  value: this.safeDivide(gop.actual || 0, income.actual || 0),
                  color: COLOR_BLUE,
                },
              ];
            } else {
              this.gopList = [];
              this.processIncomeList = [];
            }

            if (yearIncomeData?.success && yearIncomeData?.data?.length > 0) {
              const yearIncomeList = yearIncomeData.data;
              const income = yearIncomeList
                .filter((i) => ['0101', '0102', '0105'].includes(i.subjectCode))
                .reduce(
                  (acc, item) => {
                    acc.actual += item.actual || 0;
                    acc.budget += item.budget || 0;
                    return acc;
                  },
                  { actual: 0, budget: 0, lActual: 0 }
                );
              this.processIncomeList = [...yearIncomeList];
              this.processIncomeList.push({
                ...income,
                subjectName: '总收入',
                subjectCode: '01',
              });
            }

            localStorage.setItem(Constant.STORAGE_HOTEL_NAME, this.currentHotel.code);
            this.loading = false;
          })
          .catch((error) => {
            console.error('获取数据失败:', error);
            this.loading = false;
            this.incomeList = [];
            this.processIncomeList = [];
            this.gopList = [];
          });
      },
      getIncomeChartOption() {
        let totalSum = this.incomeList
          .filter((i) => ['0101', '0102', '0105'].includes(i.subjectCode))
          .reduce((acc, item) => {
            if (!acc) {
              acc = {
                actual: 0,
                budget: 0,
                lActual: 0,
              };
            }
            acc.actual += item.actual;
            acc.budget += item.budget;
            acc.lActual += item.lActual;
            return acc;
          }, null);

        let option = {
          grid: {
            top: '13%',
            right: '15%',
          },
          tooltip: {
            show: false,
            triggerOn: 'none',
          },
          yAxis: {
            axisLabel: {
              fontSize: 14,
              fontWeight: 600,
            },
            data: this.incomeList.map((i) => i.subjectName),
            axisTick: {
              show: false,
            },
          },
          xAxis: {
            splitLine: {
              show: false,
            },
            axisLabel: {
              formatter: (value) => {
                return this.currencyWNFormatter(value, 0);
              },
            },
          },
          series: [
            {
              type: 'bar',
              name: '实际',
              data: this.incomeList.map((i) => i.actual),
              barGap: '-150%',
              itemStyle: {
                color: '#212a7c',
                barBorderRadius: [5, 5, 5, 5],
              },
              z: 1,
              barWidth: 15,
            },
            {
              type: 'bar',
              name: '预算',
              data: this.incomeList.map((i) => i.budget),
              itemStyle: {
                color: '#a89ec3',
                opacity: 0.8,
                barBorderRadius: [5, 5, 5, 5],
              },
              z: 0,
              barWidth: 30,
            },
            {
              type: 'custom',
              name: '去年同期',
              renderItem: this.renderItem,
              encode: {
                x: 1,
                y: 0,
              },
              data: this.incomeList.map((i) => i.lActual),
              z: 100,
            },
            {
              type: 'custom',
              name: '增长率',
              renderItem: this.renderRateItem,
              data: this.incomeList.map((i, index) => {
                return [index, i.actual, i.lActual, i.budget];
              }),
              z: 100,
            },
            {
              type: 'custom',
              name: '汇总',
              renderItem: this.renderSummaryItem,
              data: this.incomeList.map((i, index) => {
                return [index, i.actual, i.lActual, i.budget];
              }),
              z: 0,
              silent: true,
            },
          ],
          graphic: [
            {
              type: 'text',
              left: '4%',
              top: '5%',
              style: {
                text: '总收入',
                textAlign: 'right',
                fontSize: 14,
                fontWeight: 600,
              },
            },
            {
              type: 'group',
              left: '10%',
              top: 0,
              children: [
                {
                  type: 'rect',
                  shape: {
                    x: 0,
                    y: 0,
                    width: 540,
                    height: 70,
                    r: [10, 10, 10, 10],
                  },
                  style: { fill: COLOR_GROUND },
                },
                {
                  type: 'text',
                  left: 10,
                  top: 26,
                  style: {
                    text: MathUtil.currencyWNFormatter(totalSum.actual, 0),
                    fontSize: 18,
                    fontWeight: 600,
                    textAlign: 'left',
                  },
                },
                {
                  type: 'group',
                  left: 90,
                  top: 20,
                  children: [
                    {
                      type: 'text',
                      style: {
                        text: `预算：${MathUtil.currencyWNFormatter(totalSum.budget, 0)} `,
                        textAlign: 'right',
                      },
                    },
                    {
                      type: 'group',
                      left: 4,
                      children: [
                        {
                          type: 'text',
                          style: {
                            text: `${totalSum.actual >= totalSum.budget ? '+' : ''}${MathUtil.currencyWNFormatter(
                              totalSum.actual - totalSum.budget,
                              0
                            )} `,
                            fill: totalSum.actual > totalSum.budget ? COLOR_GREEN : COLOR_RED,
                            textAlign: 'right',
                          },
                        },
                        {
                          type: 'text',
                          left: 4,
                          style: {
                            text: `完成率：${MathUtil.comPercent2Formatter(totalSum.actual, totalSum.budget, 1)}`,
                          },
                        },
                      ],
                    },
                  ],
                },
                {
                  type: 'group',
                  left: 90,
                  top: 36,
                  children: [
                    {
                      type: 'text',
                      style: {
                        text: `去年：${MathUtil.currencyWNFormatter(totalSum.lActual, 0)} `,
                        textAlign: 'right',
                      },
                    },
                    {
                      type: 'group',
                      left: 4,
                      children: [
                        {
                          type: 'text',
                          style: {
                            text: `${totalSum.actual >= totalSum.lActual ? '+' : ''}${MathUtil.currencyWNFormatter(
                              totalSum.actual - totalSum.lActual,
                              0
                            )} `,
                            fill: totalSum.actual > totalSum.lActual ? COLOR_GREEN : COLOR_RED,
                            textAlign: 'right',
                          },
                        },
                        {
                          type: 'group',
                          left: 4,
                          children: [
                            {
                              type: 'polygon',
                              right: 1,
                              top: 2,
                              shape: {
                                points: this.getTrianglePoint([0, 0], 4, totalSum.actual > totalSum.lActual),
                              },
                              style: {
                                fill: totalSum.actual > totalSum.lActual ? COLOR_GREEN : COLOR_RED,
                              },
                            },
                            {
                              type: 'text',
                              left: 4,
                              style: {
                                text: `${MathUtil.diffPercent2Formatter(totalSum.actual, totalSum.lActual, 1)}`,
                                fill: totalSum.actual > totalSum.lActual ? COLOR_GREEN : COLOR_RED,
                              },
                            },
                          ],
                        },
                      ],
                    },
                  ],
                },
              ],
            },
            {
              type: 'group',
              left: '80%',
              top: 0,
              children: [
                {
                  type: 'rect',
                  shape: {
                    width: 160,
                    height: 70,
                    r: [10, 10, 10, 10],
                  },
                  style: { fill: COLOR_GROUND_DEEP },
                },
                {
                  type: 'text',
                  left: 20,
                  top: 12,
                  style: {
                    text: '单位：',
                    textAlign: 'left',
                  },
                },
                {
                  type: 'text',
                  left: 20,
                  top: 26,
                  style: {
                    text: '万元',
                    textAlign: 'left',
                  },
                },
                {
                  type: 'line',
                  left: 60,
                  top: 8,
                  shape: {
                    x1: 0,
                    y1: 0,
                    x2: 0,
                    y2: 48,
                  },
                  style: {
                    stroke: '#ffffff',
                    fill: null,
                  },
                },
                {
                  type: 'rect',
                  left: 80,
                  top: 12,
                  shape: {
                    x: 0,
                    y: 0,
                    width: 9,
                    height: 9,
                  },
                  style: { fill: COLOR_BLUE },
                },
                {
                  type: 'text',
                  left: 93,
                  top: 10,
                  style: {
                    text: '实际',
                    textAlign: 'left',
                  },
                },
                {
                  type: 'rect',
                  left: 80,
                  top: 30,
                  shape: {
                    x: 0,
                    y: 0,
                    width: 9,
                    height: 9,
                  },
                  style: { fill: COLOR_PURPLE },
                },
                {
                  type: 'text',
                  left: 93,
                  top: 28,
                  style: {
                    text: '预算',
                    textAlign: 'left',
                  },
                },
                {
                  type: 'polygon',
                  left: 80,
                  top: 48,
                  shape: {
                    points: this.getTrianglePoint([0, 0], 4, false),
                  },
                  style: {
                    fill: COLOR_WARN,
                  },
                },
                {
                  type: 'text',
                  left: 93,
                  top: 46,
                  style: {
                    text: '去年',
                    textAlign: 'left',
                  },
                },
              ],
            },
          ],
        };

        return option;
      },
      renderItem(params, api) {
        const yValue = api.value(0);
        const xValue = api.value(1);
        const point = api.coord([xValue, yValue]);
        const linewidth = 20;
        const shapeHight = 5;
        const shapeWidth = 3;
        const style = api.style({
          stroke: COLOR_WARN,
          fill: null,
        });
        style.lineDash = [2, 2];
        const shapeStyle = api.style({
          fill: COLOR_WARN,
        });

        return {
          type: 'group',
          children: [
            {
              type: 'line',
              shape: {
                x1: point[0],
                y1: point[1] - linewidth,
                x2: point[0],
                y2: point[1] + linewidth,
              },
              style: style,
            },
            {
              type: 'polygon',
              shape: {
                points: [
                  [point[0], point[1] - linewidth],
                  [point[0] - shapeWidth, point[1] - linewidth - shapeHight],
                  [point[0] + shapeWidth, point[1] - linewidth - shapeHight],
                ],
              },
              style: shapeStyle,
            },
          ],
        };
      },
      renderRateItem(params, api) {
        const yValue = api.value(0);
        const aValue = api.value(1);
        const lValue = api.value(2);
        const bValue = api.value(3);
        const point = api.coord([0, yValue]);
        const xPoint = 20;
        const yInterval = 15;
        const xInterval = 10;
        const textY = point[1] + yInterval;
        const text1 = '预算：';
        const text1X = point[0] + xPoint;
        const text2 = `${aValue >= bValue ? '+' : ''}${MathUtil.currencyWNFormatter(aValue - bValue, 0)}`;
        const text2X = text1X + echarts.format.getTextRect(text1).width;
        const text3 = `完成率：${MathUtil.comPercent2Formatter(aValue, bValue, 1)}`;
        const text3X = text2X + echarts.format.getTextRect(text2).width + xInterval;
        const text4 = '去年：';
        const text4X = text3X + echarts.format.getTextRect(text3).width + xInterval;
        const text5 = `${aValue >= lValue ? '+' : ''}${MathUtil.currencyWNFormatter(aValue - lValue, 0)}`;
        const text5X = text4X + echarts.format.getTextRect(text4).width;
        const text6X = text5X + echarts.format.getTextRect(text5).width + xInterval + 2;
        const text7 = `${MathUtil.diffPercent2Formatter(aValue, lValue, 1)}`;
        const text7X = text6X + 6;

        return {
          type: 'group',
          children: [
            {
              type: 'text',
              style: {
                text: '预算：',
                x: point[0] + xPoint,
                y: textY,
              },
            },
            {
              type: 'text',
              style: {
                text: text2,
                x: text2X,
                y: textY,
                fill: aValue >= bValue ? COLOR_GREEN : COLOR_RED,
              },
            },
            {
              type: 'text',
              style: {
                text: text3,
                x: text3X,
                y: textY,
                fontSize: 12,
              },
            },
            {
              type: 'text',
              style: {
                text: text4,
                x: text4X,
                y: textY,
              },
            },
            {
              type: 'text',
              style: {
                text: text5,
                x: text5X,
                y: textY,
                fill: aValue >= lValue ? COLOR_GREEN : COLOR_RED,
              },
            },
            {
              type: 'polygon',
              shape: {
                points: this.getTrianglePoint([text6X, textY + 6], 4, aValue > lValue),
              },
              style: {
                fill: aValue >= lValue ? COLOR_GREEN : COLOR_RED,
              },
            },
            {
              type: 'text',
              style: {
                text: text7,
                x: text7X,
                y: textY,
                fill: aValue >= lValue ? COLOR_GREEN : COLOR_RED,
              },
            },
          ],
        };
      },
      renderSummaryItem(params, api) {
        const yValue = api.value(0);
        const actual = api.value(1);
        const lValue = api.value(2);
        const bValue = api.value(3);
        const point = api.coord([0, yValue]);
        const echartsWidth = api.getWidth();
        const yInterval = 34;
        const xpad = 8;
        const ypad = 5;

        return {
          type: 'group',
          children: [
            {
              type: 'rect',
              shape: {
                x: params.coordSys.x,
                y: point[1] - yInterval,
                width: echartsWidth - params.coordSys.x,
                height: 65,
                r: [10, 10, 10, 10],
              },
              style: { fill: COLOR_GROUND },
            },
            {
              type: 'text',
              style: {
                text: this.currencyWNFormatter(actual),
                x: echartsWidth - xpad,
                y: point[1] - yInterval + ypad,
                textAlign: 'right',
                fontSize: 18,
                fontWeight: 600,
              },
            },
            {
              type: 'text',
              style: {
                text: `预算：${MathUtil.currencyWNFormatter(bValue, 0)}`,
                x: echartsWidth - xpad,
                y: point[1] - yInterval + ypad + 22,
                textAlign: 'right',
              },
            },
            {
              type: 'text',
              style: {
                text: `去年：${MathUtil.currencyWNFormatter(lValue, 0)}`,
                x: echartsWidth - xpad,
                y: point[1] - yInterval + ypad + 22 + 16,
                textAlign: 'right',
              },
            },
          ],
        };
      },
      getTrianglePoint(point, interval = 5, rise = true) {
        return [
          [point[0], rise ? point[1] - interval : point[1] + interval],
          [point[0] - interval, rise ? point[1] + interval : point[1] - interval],
          [point[0] + interval, rise ? point[1] + interval : point[1] - interval],
        ];
      },
      getProgressIncomeOption() {
        return {
          grid: {
            top: '10%',
            left: '20%',
            right: '15%',
            bottom: '10%',
          },
          tooltip: {
            show: false,
            triggerOn: 'none',
          },
          yAxis: {
            axisLabel: {
              fontWeight: 400,
            },
            data: this.processIncomeList.map((i) => i.subjectName),
            axisTick: {
              show: false,
            },
          },
          xAxis: {
            max: 1,
            show: false,
          },
          series: [
            {
              type: 'bar',
              barGap: '-100%',
              left: '20%',
              barWidth: 12,
              itemStyle: {
                color: COLOR_PURPLE,
              },
              data: this.processIncomeList.map(() => 1),
            },
            {
              type: 'bar',
              left: '20%',
              barWidth: 12,
              itemStyle: {
                color: COLOR_BLUE,
              },
              data: this.processIncomeList.map((i) => MathUtil.completRate(i.actual, i.budget)),
            },
            {
              type: 'custom',
              name: '进度',
              renderItem: this.renderProgressIncomeItem,
              data: this.processIncomeList.map((i, index) => [index, 1, MathUtil.completRate(i.actual, i.budget)]),
            },
          ],
        };
      },
      renderProgressIncomeItem(params, api) {
        const yValue = api.value(0);
        const xValue = api.value(1);
        const value = api.value(2);
        const point = api.coord([xValue, yValue]);
        return {
          type: 'text',
          style: {
            text: this.percent2DFormatter(value, 0),
            x: point[0] + 10,
            y: point[1] - 6,
          },
        };
      },
      filterOption(input, option) {
        return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
      },
      getTimeProgressOption() {
        const currentMonth = parseInt(this.lastMonth.slice(4));
        return {
          series: [
            {
              type: 'liquidFill',
              data: [currentMonth / 12],
              radius: '80%',
              color: [COLOR_BLUE],
              backgroundStyle: {
                color: '#fff',
              },
              label: {
                formatter: () => {
                  return `${currentMonth}/12\n时间进度`;
                },
                fontSize: 20,
                color: COLOR_BLUE,
              },
            },
          ],
        };
      },
      getIncomeProgressOption() {
        return {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow',
            },
          },
          grid: {
            top: '10%',
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true,
          },
          xAxis: {
            type: 'value',
            max: 1,
            axisLabel: {
              formatter: '{value}%',
            },
          },
          yAxis: {
            type: 'category',
            data: this.processIncomeList.map((i) => i.subjectName),
          },
          series: [
            {
              type: 'bar',
              data: this.processIncomeList.map((i) => ({
                value: MathUtil.safeDivide(i.actual, i.budget),
                itemStyle: {
                  color: COLOR_BLUE,
                },
              })),
            },
          ],
        };
      },
      handleSelectChange(value) {
        this.currentHotel = {
          code: value,
          name: this.hotelList.filter((h) => h.value === value)[0].label,
        };
        const accName = this.accList.filter((a) => a.value === this.currentAcc)[0].label;
        this.reportCode = `${REPORT_CODE}-${this.currentAcc}-${this.currentHotel.code}-${this.lastMonth}`;
        this.reportName = `${REPORT_NAME}-${accName}-${this.currentHotel.name}-${this.lastMonth}`;
        this.fetchData();
      },
      handleAccSelect(value) {
        const name = this.accList.filter((h) => h.value === value)[0].label;
        this.currentAcc = value;
        this.reportCode = `${REPORT_CODE}-${value}-${this.currentHotel.code}-${this.lastMonth}`;
        this.reportName = `${REPORT_NAME}-${name}-${this.currentHotel.name}-${this.lastMonth}`;
        this.fetchData();
      },
      handleDateSelect() {
        const name = this.accList.filter((h) => h.value === this.currentAcc)[0].label;
        this.reportCode = `${REPORT_CODE}-${this.currentAcc}-${this.currentHotel.code}-${this.lastMonth}`;
        this.reportName = `${REPORT_NAME}-${name}-${this.currentHotel.name}-${this.lastMonth}`;
        this.fetchData();
      },
      formatAmount(value) {
        return MathUtil.currencyWNFormatter(value, 0);
      },
      formatPercent(value, showSign = false) {
        if (showSign) {
          return (value >= 0 ? '+' : '') + MathUtil.percent2DFormatter(value, 1);
        }
        return MathUtil.percent2DFormatter(value, 1);
      },
      currencyWFormatter(value, dot = 2, unit = '万') {
        return MathUtil.currencyWFormatter(value, dot, unit);
      },
      currencyWNFormatter(value, dot = 0) {
        return MathUtil.currencyWNFormatter(value, dot);
      },
      percent2DFormatter(value, dot = 2) {
        return MathUtil.percent2DFormatter(value, dot);
      },
      diffPercent2Formatter(thisData, lastData, dot = 2) {
        return MathUtil.diffPercent2Formatter(thisData, lastData, dot);
      },
      dot2Formatter(value, dot = 2) {
        return MathUtil.dot2Formatter(value, dot);
      },
      dateRangeFormatter(dataRange) {
        return DateUtil.dateRangeFormatter(dataRange);
      },
      dateFormatter(data) {
        return DateUtil.dateFormatter(data);
      },
      monthFormatter(data) {
        return DateUtil.monthFormatter(data);
      },
      safeDivide(numerator, denominator) {
        return MathUtil.safeDivide(numerator, denominator);
      },
    },
  };
</script>

<style lang="less" scoped>
  .main-content {
    padding: 15px 0 5px 0;
  }

  .total-income {
    background: #f7f5f4;
    padding: 10px 20px;
    border-radius: 0.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;

    .total-left {
      font-size: 16px;
      font-weight: 600;
      color: #000;
      .label {
        margin-right: 20px;
      }
      .amount {
        // display: block;
        // margin-top: 8px;
      }
      .unline {
        text-decoration: underline;
        text-underline-offset: 5px; /* 控制下划线与文字的间距 */
      }
    }

    .total-right {
      display: flex;
      // flex-direction: column;
      gap: 15px;
      .border-dashed {
        height: 26px;
        border-right: 1px dashed #000;
      }
      .budget-line,
      .last-year-line {
        display: flex;
        align-items: center;
        white-space: nowrap;

        .label {
          color: #000;
          margin-right: 12px;
        }

        .diff {
          margin-right: 12px;
          &.up {
            color: #00b42a;
          }
          &.down {
            color: #f53f3f;
          }
        }

        .rate {
          display: flex;
          align-items: center;

          .triangle {
            display: inline-block;
            width: 0;
            height: 0;
            margin-right: 4px;
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;

            &.up {
              border-bottom: 6px solid #00b42a;
            }
            &.down {
              border-top: 6px solid #f53f3f;
            }
          }

          span {
            &.up {
              color: #00b42a;
            }
            &.down {
              color: #f53f3f;
            }
          }
        }
      }
    }
  }

  .content-wrapper {
    display: flex;
    // gap: 24px;
  }

  .left-section {
    flex: 7;
    background: #fff;
    border-radius: 8px;
    padding: 25px;
  }
  .split-line {
    width: 15px;
  }
  .right-section {
    flex: 3;
    height: 100%;
  }

  .income-detail {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 20px;

    .detail-item {
      background: #f7f5f4;
      border-radius: 8px;
      padding: 16px;

      .item-header {
        margin-bottom: 12px;
        font-size: 16px;
        font-style: normal;
        font-weight: 600;
        color: #000;
      }

      .item-content {
        .actual {
          font-size: 16px;
          font-weight: 600;
          color: #000;
          // margin-bottom: 12px;
        }

        .budget,
        .last-year {
          font-size: 14px;
          margin-bottom: 8px;

          &-label {
            margin-bottom: 4px;
            // font-weight: 600;
            color: #000;
          }

          &-value {
            margin-bottom: 4px;
            font-weight: 600;
            color: #000;
          }

          &-rate {
            display: flex;
            align-items: center;

            .triangle {
              display: inline-block;
              width: 0;
              height: 0;
              margin-right: 4px;
              border-left: 3px solid transparent;
              border-right: 3px solid transparent;

              &.up {
                border-bottom: 5px solid #00b42a;
              }
              &.down {
                border-top: 5px solid #f53f3f;
              }
            }

            span {
              &.up {
                color: #00b42a;
              }
              &.down {
                color: #f53f3f;
              }
            }
          }
        }

        .divider {
          font-size: 12px;
          color: #666;
          margin: 8px 0;
          text-align: center;
        }
      }
    }
  }

  .income-chart {
    height: 400px;
    border-radius: 8px;
  }

  .gop-card {
    margin-bottom: 24px;
    height: 280px;
    border-radius: 8px;
  }

  .progress-card {
    .progress-content {
      display: grid;
      grid-template-rows: auto 1fr;
      gap: 20px;
      position: relative;
      .progress-time {
        height: 200px;
        width: 80%;
        position: absolute;
        right: 0;
        top: -48px;
      }

      .progress-income {
        height: 350px;
        margin-top: 130px;
      }
    }
  }
  .legend-wrap {
    display: flex;
    align-items: end;
  }
  .legend-item {
    background: #e9e7f2 !important;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    height: 160px;
  }

  .legend-title {
    font-size: 12px;
    color: #666;
    text-align: center;
  }

  .legend-content {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .legend-row {
    display: flex;
    align-items: center;
    gap: 8px;

    span {
      font-size: 12px;
      color: #666;
      margin-right: 12px;
    }
  }

  .legend-box {
    width: 10px;
    height: 10px;
    border-radius: 2px;
  }

  .legend-triangle {
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-bottom: 8px solid;
  }

  @media @desktop {
    .row-content {
      display: flex;
      margin-bottom: 12px;
    }

    .card-flex-all {
      flex: 1 1 calc(100% - 10px);
    }

    .card-flex-70 {
      flex: 1 1 calc(68% - 10px);
      margin-right: 10px;
    }

    .card-flex-30 {
      flex: 0 0 calc(30% - 10px);
      display: flex;
      flex-direction: column;
    }

    .gop-card {
      margin-bottom: 10px;
    }

    .card-in-flex {
      display: flex;
    }

    .card-in-flex-30 {
      flex: 1;
    }

    .card-in-flex-70 {
      flex: 2;
    }

    .card-flex-70 .echarts {
      width: 100% !important;
      // height: 400px !important;
    }

    .gop-card .echarts,
    .card-flex-30 .echarts {
      width: 100% !important;
      height: 200px !important;
    }

    .card-in-flex-30 .echarts {
      width: 100% !important;
      height: 130px !important;
    }

    .card-in-flex-70 .echarts {
      width: 100% !important;
      height: 200px !important;
    }

    .main-frame-desktop-header {
      padding: 1rem;
      background: #fff;
      overflow: hidden;
    }
  }
</style>
